﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Server;
using System.Data;
using EAGL.Server;
using EAGL.Core;
using EAGL.Data;

namespace EAGL.Search
{
    /// <summary>
    /// Use AttributeSearcher to facilitate the attribute search operations.
    /// </summary>
    public class AttributeSearcher: IServerApplicable
    {
        #region =========================== PRIVATE ===============================

        protected IFeatureClass featureClass;
        protected string fieldsClause;
        protected string whereClause;
  
        protected bool serverMode;
        protected IServerContext serverContext;

        
        // creates the required fields in the output data table
        protected List<IField> createFields(IFeatureCursor cur)
        {
            List<IField> fields;
            if (fieldsClause == null || fieldsClause == "")
            {
                fields = GeneralConvertor.ListOf(cur.Fields);
            }
            else
            {
                List<string> ss = GeneralConvertor.ListOf(fieldsClause, true);
                List<IField> ll = GeneralConvertor.ListOf(cur.Fields);
                fields = GeneralConvertor.ListOf(ss, ll);
            }
            return fields;
        }

        #endregion

        #region =========================== PUBLIC  ===============================

        public IFeatureClass FeatureClass
        {
            get { return this.featureClass; }
            set { this.featureClass = value;  }
        }

        /// <summary>
        /// A comma separated string represets the fields you want in the result
        /// </summary>
        public string FieldsClause
        {
            get { return fieldsClause; }
            set { this.fieldsClause = value; }
        }

        /// <summary>
        /// The condition of search
        /// </summary>
        public string WhereClause 
        {
            get { return whereClause; }
            set { this.whereClause = value; }
        }

        /// <summary>
        /// Determines if the instance will work in server mode, if you put this property to true
        /// then you have to supply the ServerContext property
        /// </summary>
        public bool ServerMode 
        {
            get { return serverMode; }
            set { this.serverMode = value; }
        }

        /// <summary>
        /// Server context is used when working in server mode, see ServerMode property
        /// </summary>
        public IServerContext ServerContext
        {
            get { return serverContext; }
            set { this.serverContext = value; }
        }


        public AttributeSearcher()
        { }
        
        public AttributeSearcher(IFeatureLayer featureLayer)
        {
            this.featureClass = featureLayer.FeatureClass;
        }

        public AttributeSearcher(IFeatureClass featureClass)
        {
            this.featureClass = featureClass;
        }

        /// <summary>
        /// Searches the supplied feature class
        /// </summary>
        /// <returns>DataTable represents the search result</returns>
        public virtual DataTable Search()
        {

            if (this.featureClass == null)
            {
                throw (new Exception("Feature Class not assigned."));
            }


            IQueryFilter qf;
            if (serverMode)
            {
                qf = serverContext.CreateObject("esriGeoDatabase.QueryFilter") as IQueryFilter;
            }
            else
            {
                qf = new QueryFilterClass();
            }


            qf.SubFields = this.fieldsClause;
            qf.WhereClause = this.whereClause;

            IFeatureCursor cur = this.featureClass.Search(qf, false);


            // Create the table
            // It seems the fields property of the cursor is the same as the featute class
            // even though the SubFields property is not empty, so we need to create the table 
            // using another approach

            List<IField> fields = createFields(cur);

            DataTableBuilder builder = new DataTableBuilder(fields);

            DataTable table = new DataTable();
            table = builder.DataTable;

            // Fill the table
            DataTableAdapter adapter = new DataTableAdapter((ICursor)cur);
            adapter.Fill(table);
            return table;
        }

        #endregion

    }
}
